package avicit.bdp.dds.api.controller;

import avicit.bdp.common.dto.upload.ResumeUploadDto;
import avicit.bdp.common.utils.redis.RedisCacheHelper;
import avicit.bdp.common.utils.uploads.CatalogBean;
import avicit.bdp.common.utils.uploads.FileBean;
import avicit.bdp.dds.api.dto.CatalogDto;
import avicit.bdp.dds.api.dto.FileDto;
import avicit.bdp.dds.api.service.FileService;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 文件管理REST接口
 */
@RestController
@RequestMapping("/api/bdp/dds/file/FileRest")
@Api(tags = "文件管理接口")
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    private final FileService fileService;
    private final RedisCacheHelper redisCacheHelper;

    @Autowired
    public FileController(FileService fileService, RedisCacheHelper redisCacheHelper) {
        this.fileService = fileService;
        this.redisCacheHelper = redisCacheHelper;
    }

    /**
     * 文件上传
     */
    @ApiOperation(value = "文件上传")
    @PostMapping("/upload")
    public ResponseMsg<String> upload(ResumeUploadDto resumeUploadDto,
                                      HttpServletResponse response) throws Exception {
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        Long startTime = System.currentTimeMillis();

        try {
            fileService.upload(resumeUploadDto);
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
            responseMsg.setErrorDesc(e.getMessage());
            logger.error(e.getMessage(), e);
        }

        Long endTime = System.currentTimeMillis();
        logger.info("上传文件{}--{}/{}，开始时间：{}，结束时间：{}，耗时：{}", resumeUploadDto.getFile().getOriginalFilename(),
                resumeUploadDto.getChunk(), resumeUploadDto.getChunks(), startTime, endTime, endTime - startTime);

        return responseMsg;
    }

    @PostMapping("/mergeChunks")
    @ApiOperation(value = "获取文件上传是否成功，成功，暂停，失败的话响应，否则等待")
    public ResponseMsg<Map<String, String>> mergeChunks(@RequestBody ResumeUploadDto resumeUploadDto) throws Exception {
        ResponseMsg<Map<String, String>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.mergeChunks(resumeUploadDto));
        return responseMsg;
    }

    @ApiOperation(value = "获取已经上传的分片信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileMd5", value = "文件唯一标识", dataType = "String"),
            @ApiImplicitParam(name = "hdfsPath", value = "hdfsPath", dataType = "String"),
            @ApiImplicitParam(name = "fileName", value = "文件名称", dataType = "String")
    })
    @GetMapping("/upload")
    public ResponseMsg<Map<String, List<Integer>>> getUploadedChunkInfoList(
            @RequestParam String fileMd5,
            @RequestParam String hdfsPath,
            @RequestParam(required = false) String fileName) throws Exception {
        ResponseMsg<Map<String, List<Integer>>> responseMsg = new ResponseMsg<>();
        Long startTime = System.currentTimeMillis();
        responseMsg.setResponseBody(fileService.getUploadedChunkInfos(fileMd5, hdfsPath, fileName));
        Long endTime = System.currentTimeMillis();
        logger.info("开始时间：{}，结束时间：{}，耗时：{}", startTime, endTime, endTime - startTime);
        return responseMsg;
    }

    @DeleteMapping("/deleteFileUpload")
    @ApiOperation(value = "删除文件上传")
    public ResponseMsg<Boolean> deleteFileUpload(@RequestBody ResumeUploadDto resumeUploadDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteFileUpload(resumeUploadDto.getFileMd5(), resumeUploadDto.getHdfsPath(),
                resumeUploadDto.getFileName()));
        return responseMsg;
    }


    @ApiOperation(value = "查询文件列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileName", value = "文件名称", dataType = "String"),
            @ApiImplicitParam(name = "catalogPath", value = "目录路径", dataType = "String"),
            @ApiImplicitParam(name = "startTime", value = "开始时间", dataType = "Long"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", dataType = "Long"),
            @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String")
    })
    @GetMapping("/getFileList")
    public ResponseMsg<List<FileBean>> getFileList(@RequestParam(required = false) String fileName,
                                                   @RequestParam String catalogPath,
                                                   @RequestParam(required = false) Long startTime,
                                                   @RequestParam(required = false) Long endTime,
                                                   @RequestParam String projectId) throws Exception {
        ResponseMsg<List<FileBean>> responseMsg = new ResponseMsg<>();
        List<FileBean> queryRespBean = fileService.getFileList(fileName, catalogPath, startTime, endTime, projectId);
        responseMsg.setResponseBody(queryRespBean);
        return responseMsg;
    }

    @ApiOperation(value = "查询目录及文件树")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "路径", name = "path", dataType = "String"),
            @ApiImplicitParam(value = "默认的路径", name = "defaultFilePath", dataType = "String"),
            @ApiImplicitParam(value = "数据空间ID", name = "projectId", dataType = "String"),
            @ApiImplicitParam(value = "类型", name = "type", dataType = "String")
    })
    @GetMapping("/getFileTreeList")
    public ResponseMsg<CatalogBean> getFileTreeList(@RequestParam(required = false) String path,
                                                    @RequestParam(required = false) String defaultFilePath,
                                                    @RequestParam String projectId,
                                                    @RequestParam String type) throws Exception {
        ResponseMsg<CatalogBean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getFileTreeList(projectId, path, type, defaultFilePath));
        return responseMsg;
    }

    @DeleteMapping("/deleteFileByPaths")
    @ApiOperation(value = "删除文件")
    public ResponseMsg<Boolean> deleteFileByPaths(@RequestBody FileDto fileDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteFileByPaths(fileDto.getFilePath()));
        return responseMsg;
    }

    @ApiOperation(value = "查询目录树")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "父分类路径", name = "parentCatalogPath", dataType = "String"),
            @ApiImplicitParam(value = "数据空间ID", name = "projectId", dataType = "String")
    })
    @GetMapping("/getCatalogTree")
    public ResponseMsg<CatalogBean> getCatalogTree(@RequestParam(required = false) String parentCatalogPath,
                                                   @RequestParam String projectId) throws Exception {
        ResponseMsg<CatalogBean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getCatalogTree(parentCatalogPath, projectId));
        return responseMsg;
    }

    @ApiOperation(value = "查询目录树")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "父分类路径", name = "parentCatalogPath", dataType = "String"),
            @ApiImplicitParam(value = "数据空间ID", name = "projectId", dataType = "String")
    })
    @GetMapping("/getCatalogTreeByCatalogPath")
    public ResponseMsg<List<CatalogBean>> getCatalogTreeByCatalogPath(@RequestParam String parentCatalogPath,
                                                                      @RequestParam String projectId) throws Exception {
        ResponseMsg<List<CatalogBean>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getCatalogTreeByCatalogPath(parentCatalogPath, projectId));
        return responseMsg;
    }

    @ApiOperation(value = "删除目录")
    @DeleteMapping("/deleteCatalogByPath")
    public ResponseMsg<Boolean> deleteCatalogByPath(@RequestBody CatalogDto catalogDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.deleteCatalogByPath(catalogDto.getCatalogPath()));
        return responseMsg;
    }

    @ApiOperation(value = "创建目录")
    @PostMapping("/saveCatalog")
    public ResponseMsg<Boolean> saveCatalog(@RequestBody CatalogDto catalogDto) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.saveCatalog(catalogDto));
        return responseMsg;
    }

    @ApiOperation(value = "下载文件")
    @ApiImplicitParam(value = "文件路径", name = "filePath", dataType = "String")
    @GetMapping("/downloadFile")
    public void downloadFile(@RequestParam String filePath, HttpServletRequest request, HttpServletResponse response) {
        try {
            fileService.downloadFile(filePath, request, response);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    @ApiOperation(value = "重命名文件")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "源文件名全路径", name = "srcPath", dataType = "String"),
            @ApiImplicitParam(value = "目的文件名全路径", name = "dstPath", dataType = "String")
    })
    @GetMapping("/rename")
    public ResponseMsg<Boolean> rename(@RequestParam String srcPath, @RequestParam String dstPath) throws Exception {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.rename(srcPath, dstPath));
        return responseMsg;
    }

    @GetMapping("/getChunkSize")
    @ApiOperation(value = "获取分片大小")
    public ResponseMsg<Long> getChunkSize() {
        ResponseMsg<Long> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getChunkSize());
        return responseMsg;
    }

    @GetMapping("/getUploadType")
    @ApiOperation(value = "获取上传类型")
    public ResponseMsg<Boolean> getUploadType() {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.getUploadType());
        return responseMsg;
    }

    @ApiOperation(value = "判断文件是否存在")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileList", value = "文件名称集合", dataType = "List",  paramType = "body",required = true),
            @ApiImplicitParam(name = "catalogPath", value = "目录路径", dataType = "String", paramType = "body",required = true)
    })
    @PostMapping("/checkFileExist")
    public ResponseMsg<Map<String, Boolean>> checkFileExist(@ApiIgnore @RequestBody Map<String, Object> map) throws Exception {
        ResponseMsg<Map<String, Boolean>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(fileService.checkFileExist(map));
        return responseMsg;
    }

    @ApiOperation(value = "删除redis缓存数据")
    @ApiImplicitParam(name = "key", value = "key值", dataType = "String")
    @GetMapping("/deleteRedisData")
    public ResponseMsg<Boolean> deleteRedisData(String key) {
        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        redisCacheHelper.del(key);
        responseMsg.setResponseBody(true);
        return responseMsg;
    }

}
